from SimPy.Simulation import *
from random import expovariate, seed, uniform

## Model components ------------------------

class Source(Process):
    """ Source generates customers randomly """
    def generate(self,number, meanTBA, TBA_var, resource, srvTime, pkt_type, pre_delay):
	yield hold,self,pre_delay
	for i in range(number):
            c = Customer(name = "Type%d Pkt_%d"%(pkt_type, i,))
            activate(c,c.visit(timeInBank=srvTime, res=resource))          
            t = meanTBA+uniform(0.0, TBA_var)
            yield hold,self,t
		        
class Customer(Process):
    """ Customer arrives, is served and  leaves """
    def visit(self,timeInBank=0,res=None):   
        global cur_queue_size
        if(max_queue_size > cur_queue_size):
        	arrive = now()       # arrival time
        	cur_queue_size+=1
        
        	#print "%8.9f %s Arrived QueueSize(includingSelf)= %d"%(now(),self.name, cur_queue_size)		
        	yield request,self,res                       
        	#wait = now()-arrive  # waiting time        
        	#print "%8.9f %s: Waited %6.9f"%(now(),self.name,wait)
        	yield hold,self,timeInBank               
        	yield release,self,res
       		cur_queue_size-=1
        	wait_sys = now()-arrive  # waiting time        
        	#print "%8.9f %s Waited_in_System %6.9f"%(now(),self.name,wait_sys)
        
        	#print "%8.9f %s: Departured QueueSize= %d"%(now(),self.name, cur_queue_size)
			#output arrival_time, pkt_seq, wait_time, queue_size
        	print "%8.9f, %s, %8.9f, %d"%(arrive,self.name,wait_sys,cur_queue_size)
        else:
			#print "%8.9f %s Dropped 0"%(now(),self.name)
        	print "%8.9f, %s, 0, %d"%(now(),self.name, cur_queue_size)
	
## Experiment data -------------------------

maxNumber = 10000                                                                         
#maxTime = 0.0501# minutes #3s  
maxTime = 0.167                            
k = Resource(name="Counter",unitName="Clerk")

sendingRate1 = 0.887099e9 #bit/s 100Mb/s
sendingRate2 = 0.295875e9 #
serviceRate = 0.523756e9 #978 Mb/s
packetSize = 12000 #bit, 1500 Bytes
bandwidth = 1e9 #bit, 1Gb/s

#arrivalTimeGap1 = packetSize/sendingRate1 - packetSize/bandwidth;
#arrivalTimeGap2 = packetSize/sendingRate2 - packetSize/bandwidth;
arrivalTimeGap1 = packetSize/sendingRate1
arrivalTimeGap2 = packetSize/sendingRate2
serviceTime = packetSize/serviceRate #per packet
processing_time=6e-6 #6us

max_queue_size = 20
cur_queue_size = 0
pre_delay1 = 0
#pre_delay1 = 0.00011 #delay before generating packets
#pre_delay2 = 0.00011
pre_delay2 = 0

#max_gap_var1=arrivalTimeGap1/100.0;
#max_gap_var2=arrivalTimeGap2/100.0;
max_gap_var1=0;
max_gap_var2=0;

## Model/Experiment ------------------------------
seed(99999)
initialize()
s2 = Source('Source')
activate(s2,s2.generate(number=maxNumber, meanTBA=arrivalTimeGap2, TBA_var=max_gap_var1, resource=k, srvTime=serviceTime, pkt_type=2, pre_delay=pre_delay2),at=0.0)  
s1 = Source('Source')
activate(s1,s1.generate(number=maxNumber, meanTBA=arrivalTimeGap1, TBA_var=max_gap_var2, resource=k, srvTime=serviceTime, pkt_type=1, pre_delay=pre_delay1),at=0.0)  
simulate(until=maxTime)
